grammar JSON;

@header
{
	package in.co.codedoc.json;
	
	import in.co.codedoc.util.StringUtil;
}
@lexer::header
{
	package in.co.codedoc.json;
}

jsonPayload returns [JSONValue jsonPayload] : jv = jsonValue EOF {jsonPayload = jv;};

jsonValue returns [JSONValue jsonValue] : lv = leafValue {jsonValue = lv;}| ov = objectValue {jsonValue = ov;}| av = arrayValue {jsonValue = av;};

leafValue returns [JSONValue leafValue] 
	: 
		l = LONG{leafValue = new JSONLongValue(Long.parseLong(l.getText()));}
	|
		d = DOUBLE{leafValue = new JSONDoubleValue(Double.parseDouble(d.getText()));} 
	| 
		b = BOOL{leafValue = new JSONBooleanValue(b.getText().equalsIgnoreCase("true"));}
	|
		s = STRING{leafValue = new JSONStringValue(StringUtil.StripQuotesAndEscapes(s.getText()));}
	;

objectValue returns [JSONObjectValue objectValue]
@init
{
	HashMap<JSONValue,JSONValue> nameValuePairs = new HashMap<JSONValue,JSONValue>(); 
}
	:
		(LCURLY) => {} LCURLY (nameValuePair[nameValuePairs] (COMMA nameValuePair[nameValuePairs])*)? RCURLY
		{
			objectValue = new JSONObjectValue(nameValuePairs);
		}
;

arrayValue returns [JSONArrayValue arrayValue]
@init
{
	ArrayList<JSONValue> entries = new ArrayList<JSONValue>();
}
	:
		(LSQUARE) => LSQUARE (entry = jsonValue {entries.add(entry);} (COMMA entry = jsonValue {entries.add(entry);})*)? RSQUARE
		{
			arrayValue = new JSONArrayValue(entries);
		}
	;

nameValuePair[HashMap<JSONValue,JSONValue> nameValuePairs] 
	: k = jsonValue COLON v = jsonValue {nameValuePairs.put(k,v);};

COMMA : ',';
LSQUARE : '[';
RSQUARE : ']';
LCURLY : '{';
RCURLY : '}';
COLON : ':';

LONG : ('-'|'+')?('0'..'9')+;

DOUBLE : ('-'|'+')?('0'..'9')*'.'('0'..'9')+;

BOOL : ('t''r''u''e')|('f''a''l''s''e');

STRING :  '"'(~('"'|'\\')|('\\'.))*'"'
		| '\''(~('\''|'\\')|('\\'.))*'\''
		| (('a'..'z')|('A'..'Z')|'_')(('a'..'z')|('A'..'Z')|'_'|'0'..'9')*;
		
WS : (' '|'\t'|'\r'|'\n'){$channel=HIDDEN;};
